//
// SharedPtrTest.cpp
//


#include "SharedPtr.h"
#include <string>
#include <assert.h>

namespace
{
	class TestObject
	{
	public:
		TestObject(const std::string& data): _data(data)
		{
			++_count;
		}
		
		virtual ~TestObject()
		{
			--_count;
		}
		
		const std::string& data()
		{
			return _data;
		}
		
		static int count()
		{
			return _count;
		}
		
	private:
		std::string _data;
		static int _count;
	};
	
	int TestObject::_count = 0;
}



void testSharedPtr()
{
	SharedPtr<TestObject> ptr1;
	assert(NULL == ptr1.get());
	TestObject* pTO1 = new TestObject("one");
	TestObject* pTO2 = new TestObject("two");
	if (pTO2 < pTO1)
	{
		TestObject* pTmp = pTO1;
		pTO1 = pTO2;
		pTO2 = pTmp;
	}
	assert (pTO1 < pTO2);
	ptr1 = pTO1;
	assert (ptr1.referenceCount() == 1);
	SharedPtr<TestObject> ptr2 = pTO2;
	SharedPtr<TestObject> ptr3 = ptr1;
	assert (ptr1.referenceCount() == 2);
	SharedPtr<TestObject> ptr4;
	assert (ptr1.get() == pTO1);
	assert (ptr1 == pTO1);
	assert (ptr2.get() == pTO2);
	assert (ptr2 == pTO2);
	assert (ptr3.get() == pTO1);
	assert (ptr3 == pTO1);
	
	assert (ptr1 == pTO1);
	assert (ptr1 != pTO2);
	
	assert (ptr1 == ptr3);
	assert (ptr1 != ptr2);

	assert ((ptr1->data() == "one" && ptr2->data() == "two") || (ptr1->data() == "two" && ptr2->data() == "one"));
	
	assert (!(ptr4 == ptr1));
	assert (!(ptr4 == ptr2));
	assert (ptr4 != ptr1);
	assert (ptr4 != ptr2);
	
	ptr4 = ptr2;
	assert (ptr4 == ptr2);
	assert (!(ptr4 != ptr2));
	
	assert (TestObject::count() == 2);
	ptr1 = 0;
	ptr2 = 0;
	ptr3 = 0;
	ptr4 = 0;
	assert (TestObject::count() == 0);
	
	{
		SharedPtr<TestObject> ptr = new TestObject("");
		assert (TestObject::count() == 1);
	}
	assert (TestObject::count() == 0);
}

int main()
{
	testSharedPtr();
	return 0;
}
